<template>
  <div class="editor-container">
    <textarea
      ref="editorRef"
      v-model="content"
      class="editor-textarea"
      @input="onInput"
      @scroll="onScroll"
      @dragover="onDragOver"
      @drop="onDrop"
      @paste="onPaste"
      placeholder="请输入Markdown内容... 拖拽图片到此处上传，或直接粘贴图片"
      spellcheck="false"
      autocorrect="off"
      autocomplete="off"
      autocapitalize="off"
    ></textarea>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount, watch } from 'vue'
import { useAppStore } from '../store'

// ==================== 类型定义 ====================
interface ScrollInfo {
  scrollTop: number
  scrollHeight: number
  clientHeight: number
}

interface ImageSaveResult {
  success: boolean
  absolutePath?: string
  error?: string
}

interface ElectronAPI {
  saveImage: (buffer: Uint8Array, fileName: string) => Promise<ImageSaveResult>
}

declare global {
  interface Window {
    electronAPI?: ElectronAPI
  }
}

// ==================== 组件状态 ====================
const store = useAppStore()
const editorRef = ref<HTMLTextAreaElement | null>(null)

// 滚动同步标志位，防止循环触发
let isScrollingSyncing = false

// ==================== 组件暴露 ====================
defineExpose({
  editorRef
})

// ==================== 计算属性 ====================
const content = computed({
  get: () => store.editorContent,
  set: (value: string) => store.updateEditorContent(value)
})

// ==================== 工具函数 ====================
/**
 * 防抖函数
 * @param func 要防抖的函数
 * @param wait 等待时间（毫秒）
 */
const debounce = <T extends (...args: any[]) => any>(func: T, wait: number) => {
  let timeout: NodeJS.Timeout
  return function executedFunction(...args: Parameters<T>) {
    const later = () => {
      clearTimeout(timeout)
      func(...args)
    }
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)
  }
}

/**
 * 生成带时间戳的文件名
 * @param extension 文件扩展名
 */
const generateFileName = (extension: string): string => {
  const timestamp = Date.now()
  const randomSuffix = Math.random().toString(36).substring(2, 8)
  return `pasted_image_${timestamp}_${randomSuffix}.${extension}`
}

/**
 * 检查是否为图片类型
 * @param type MIME类型
 */
const isImageType = (type: string): boolean => type.startsWith('image/')

/**
 * 从MIME类型提取文件扩展名
 * @param mimeType MIME类型
 */
const getExtensionFromMimeType = (mimeType: string): string => {
  const parts = mimeType.split('/')
  return parts[1] || 'png'
}

// ==================== 事件处理函数 ====================
/**
 * 输入事件处理（防抖）
 */
const onInputDebounced = debounce(() => {
  store.setModified(true)
}, 300)

const onInput = (): void => {
  onInputDebounced()
}

/**
 * 滚动事件处理
 */
const onScroll = (event: Event): void => {
  if (isScrollingSyncing) return
  
  const target = event.target as HTMLTextAreaElement
  const scrollInfo: ScrollInfo = {
    scrollTop: target.scrollTop,
    scrollHeight: target.scrollHeight,
    clientHeight: target.clientHeight
  }
  
  window.dispatchEvent(new CustomEvent('editor-scroll', { detail: scrollInfo }))
}

/**
 * 拖拽悬停事件处理
 */
const onDragOver = (event: DragEvent): void => {
  event.preventDefault()
  if (event.dataTransfer) {
    event.dataTransfer.dropEffect = 'copy'
  }
}

/**
 * 拖拽放置事件处理
 */
const onDrop = async (event: DragEvent): Promise<void> => {
  event.preventDefault()
  if (!event.dataTransfer?.files.length) return
  
  const imageFiles = Array.from(event.dataTransfer.files)
    .filter(file => isImageType(file.type))
  
  for (const file of imageFiles) {
    await handleImageUpload(file)
  }
}

/**
 * 粘贴事件处理
 */
const onPaste = async (event: ClipboardEvent): Promise<void> => {
  if (!event.clipboardData?.items.length) return
  
  const items = Array.from(event.clipboardData.items)
  const imageItem = items.find(item => isImageType(item.type))
  
  if (!imageItem) return
  
  event.preventDefault()
  
  const file = imageItem.getAsFile()
  if (!file) return
  
  const extension = getExtensionFromMimeType(imageItem.type)
  const fileName = generateFileName(extension)
  const namedFile = new File([file], fileName, { type: file.type })
  
  await handleImageUpload(namedFile)
}

// ==================== 图片处理 ====================
/**
 * 处理图片上传
 * @param file 图片文件
 */
const handleImageUpload = async (file: File): Promise<void> => {
  try {
    if (!window.electronAPI?.saveImage) {
      console.warn('Electron API 不可用，使用 base64 降级处理')
      await handleImageFallback(file)
      return
    }

    const arrayBuffer = await file.arrayBuffer()
    const buffer = new Uint8Array(arrayBuffer)
    
    const result = await window.electronAPI.saveImage(buffer, file.name)
    
    if (result.success && result.absolutePath) {
      const imageMarkdown = `![${file.name}](${result.absolutePath})`
      insertImageAtCursor(imageMarkdown)
    } else {
      console.error('图片保存失败:', result.error)
      await handleImageFallback(file)
    }
  } catch (error) {
    console.error('图片上传失败:', error)
    await handleImageFallback(file)
  }
}

/**
 * 图片处理降级方案（使用base64）
 * @param file 图片文件
 */
const handleImageFallback = async (file: File): Promise<void> => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    
    reader.onload = (e) => {
      const result = e.target?.result as string
      if (result) {
        const imageMarkdown = `![${file.name}](${result})`
        insertImageAtCursor(imageMarkdown)
        resolve()
      } else {
        reject(new Error('无法读取文件'))
      }
    }
    
    reader.onerror = () => reject(new Error('文件读取失败'))
    reader.readAsDataURL(file)
  })
}

// ==================== 文本操作 ====================
/**
 * 在光标位置插入图片
 * @param imageMarkdown 图片的Markdown语法
 */
const insertImageAtCursor = (imageMarkdown: string): void => {
  if (!editorRef.value) return
  
  const textarea = editorRef.value
  const { selectionStart: start, selectionEnd: end } = textarea
  
  const newContent = 
    store.editorContent.substring(0, start) + 
    imageMarkdown + 
    store.editorContent.substring(end)
  
  store.updateEditorContent(newContent)
  
  // 更新光标位置
  requestAnimationFrame(() => {
    textarea.focus()
    const newPosition = start + imageMarkdown.length
    textarea.setSelectionRange(newPosition, newPosition)
  })
}

/**
 * 在光标位置插入文本
 * @param text 要插入的文本
 */
const insertTextAtCursor = (text: string): void => {
  if (!editorRef.value) return
  
  const textarea = editorRef.value
  const { selectionStart: start, selectionEnd: end } = textarea
  
  const newContent = 
    store.editorContent.substring(0, start) + 
    text + 
    store.editorContent.substring(end)
  
  store.updateEditorContent(newContent)
  
  requestAnimationFrame(() => {
    textarea.focus()
    const newPosition = start + text.length
    textarea.setSelectionRange(newPosition, newPosition)
  })
}

// ==================== 滚动同步 ====================
/**
 * 处理预览区域滚动同步
 */
const handlePreviewScroll = (event: Event): void => {
  if (!editorRef.value) return
  
  const detail = (event as CustomEvent<ScrollInfo>).detail
  
  isScrollingSyncing = true
  
  const editorScrollTop = 
    (detail.scrollTop / detail.scrollHeight) * editorRef.value.scrollHeight
  editorRef.value.scrollTop = editorScrollTop
  
  setTimeout(() => {
    isScrollingSyncing = false
  }, 50)
}

// ==================== 生命周期钩子 ====================
/**
 * 监听store中的内容变化
 */
watch(
  () => store.currentFile.content,
  (newContent) => {
    if (content.value !== newContent) {
      content.value = newContent
    }
  }
)

/**
 * 组件挂载
 */
onMounted(() => {
  if (store.currentFile.content) {
    content.value = store.currentFile.content
  }
  
  window.addEventListener('preview-scroll', handlePreviewScroll)
})

/**
 * 组件卸载
 */
onBeforeUnmount(() => {
  window.removeEventListener('preview-scroll', handlePreviewScroll)
})
</script>

<style scoped>
.editor-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(248, 250, 252, 0.95) 100%);
  backdrop-filter: blur(10px);
  border-radius: 12px 0 0 12px;
}

.editor-textarea {
  flex: 1;
  width: 100%;
  padding: 24px;
  font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  line-height: 1.7;
  border: none;
  outline: none;
  resize: none;
  box-sizing: border-box;
  background: transparent;
  color: #2d3748;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  font-size: 15px;
  font-weight: 400;
  overflow: auto;
  scrollbar-width: thin; /* Firefox */
  scrollbar-color: rgba(102, 126, 234, 0.3) transparent; /* Firefox */
  letter-spacing: 0.3px;
  word-spacing: 1px;
}

/* 添加一些视觉增强效果 */
.editor-textarea::selection {
  background: rgba(102, 126, 234, 0.2);
  color: inherit;
}

/* Webkit浏览器的滚动条样式 */
.editor-textarea::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.editor-textarea::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.02);
  border-radius: 4px;
}

.editor-textarea::-webkit-scrollbar-thumb {
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.3) 0%, rgba(118, 75, 162, 0.3) 100%);
  border-radius: 4px;
  transition: all 0.3s ease;
}

.editor-textarea::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.5) 0%, rgba(118, 75, 162, 0.5) 100%);
  transform: scale(1.1);
}

.editor-textarea:focus {
  outline: none;
  box-shadow: 
    inset 0 0 0 2px rgba(102, 126, 234, 0.2),
    0 0 0 4px rgba(102, 126, 234, 0.1);
  background: rgba(255, 255, 255, 0.8);
}

.editor-textarea::placeholder {
  color: #a0aec0;
  font-style: italic;
  font-weight: 300;
  opacity: 0.8;
}

/* 添加打字机效果的光标动画 */
@keyframes blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0; }
}

.editor-textarea:focus {
  caret-color: #667eea;
}

/* 行号效果（通过背景实现） */
.editor-textarea {
  background-image: 
    linear-gradient(to right, rgba(102, 126, 234, 0.05) 0px, rgba(102, 126, 234, 0.05) 60px, transparent 60px),
    repeating-linear-gradient(
      transparent,
      transparent 1.7em,
      rgba(0, 0, 0, 0.03) 1.7em,
      rgba(0, 0, 0, 0.03) calc(1.7em + 1px)
    );
  background-attachment: local;
}

/* 暗色主题 */
.dark .editor-container {
  background: linear-gradient(135deg, rgba(26, 32, 44, 0.95) 0%, rgba(45, 55, 72, 0.95) 100%);
  backdrop-filter: blur(10px);
}

.dark .editor-textarea {
  color: #e2e8f0;
  scrollbar-color: rgba(76, 81, 191, 0.3) transparent; /* Firefox */
  background-image: 
    linear-gradient(to right, rgba(76, 81, 191, 0.1) 0px, rgba(76, 81, 191, 0.1) 60px, transparent 60px),
    repeating-linear-gradient(
      transparent,
      transparent 1.7em,
      rgba(255, 255, 255, 0.03) 1.7em,
      rgba(255, 255, 255, 0.03) calc(1.7em + 1px)
    );
}

.dark .editor-textarea::selection {
  background: rgba(76, 81, 191, 0.3);
  color: inherit;
}

/* Webkit浏览器的滚动条样式 - 暗色主题 */
.dark .editor-textarea::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.02);
}

.dark .editor-textarea::-webkit-scrollbar-thumb {
  background: linear-gradient(135deg, rgba(76, 81, 191, 0.3) 0%, rgba(85, 60, 154, 0.3) 100%);
}

.dark .editor-textarea::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(135deg, rgba(76, 81, 191, 0.5) 0%, rgba(85, 60, 154, 0.5) 100%);
}

.dark .editor-textarea:focus {
  box-shadow: 
    inset 0 0 0 2px rgba(76, 81, 191, 0.3),
    0 0 0 4px rgba(76, 81, 191, 0.1);
  background: rgba(26, 32, 44, 0.8);
  caret-color: #4c51bf;
}

.dark .editor-textarea::placeholder {
  color: #718096;
  opacity: 0.7;
}

/* 添加一些微妙的动画效果 */
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.editor-container {
  animation: fadeInUp 0.5s ease-out;
}

/* 响应式字体大小 */
@media (max-width: 768px) {
  .editor-textarea {
    font-size: 14px;
    padding: 16px;
  }
}

/* 高对比度模式支持 */
@media (prefers-contrast: high) {
  .editor-textarea {
    border: 1px solid #000;
  }
  
  .dark .editor-textarea {
    border: 1px solid #fff;
  }
}

/* 减少动画模式支持 */
@media (prefers-reduced-motion: reduce) {
  .editor-textarea,
  .editor-container {
    animation: none;
    transition: none;
  }
}
</style>